﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;
using YJKGridTopologyCal.Geometries.Utilities;

namespace YJKGridTopologyCal.Noding.Snapround
{
	public class GeometryNoder
	{
		public GeometryNoder(IPrecisionModel pm)
		{
			this._pm = pm;
		}

		public bool IsValidityChecked { get; set; }

		public IList<ILineString> Node(ICollection<IGeometry> geoms)
		{
			IEnumerator<IGeometry> enumerator = geoms.GetEnumerator();
			{
				if (enumerator.MoveNext())
				{
					IGeometry geometry = enumerator.Current;
					this._geomFact = geometry.Factory;
				}
			}
			IList<ISegmentString> segStrings = GeometryNoder.ToSegmentStrings(GeometryNoder.ExtractLines(geoms));
			MCIndexSnapRounder mcindexSnapRounder = new MCIndexSnapRounder(this._pm);
			((INoder)mcindexSnapRounder).ComputeNodes(segStrings);
			IList<ISegmentString> nodedSubstrings = ((INoder)mcindexSnapRounder).GetNodedSubstrings();
			if (this.IsValidityChecked)
			{
				new NodingValidator(nodedSubstrings).CheckValid();
			}
			return this.ToLineStrings(nodedSubstrings);
		}

		private IList<ILineString> ToLineStrings(IEnumerable<ISegmentString> segStrings)
		{
			List<ILineString> list = new List<ILineString>();
			foreach (ISegmentString segmentString in segStrings)
			{
				if (segmentString.Count >= 2)
				{
					list.Add(this._geomFact.CreateLineString(segmentString.Coordinates));
				}
			}
			return list;
		}

		private static IEnumerable<IGeometry> ExtractLines(IEnumerable<IGeometry> geoms)
		{
			List<IGeometry> list = new List<IGeometry>();
			LinearComponentExtracter filter = new LinearComponentExtracter(list);
			foreach (IGeometry geometry in geoms)
			{
				geometry.Apply(filter);
			}
			return list;
		}

		private static IList<ISegmentString> ToSegmentStrings(IEnumerable<IGeometry> lines)
		{
			List<ISegmentString> list = new List<ISegmentString>();
			foreach (IGeometry geometry in lines)
			{
				ILineString lineString = (ILineString)geometry;
				list.Add(new NodedSegmentString(lineString.Coordinates, null));
			}
			return list;
		}

		private IGeometryFactory _geomFact;

		private readonly IPrecisionModel _pm;
	}
}
